[Ruby on Rails]td-clientでTreasureDataにデータをimportする
はじめに
CSVファイルの中身を解析し、TreasureDataにimportするサンプルをRuby on Railsにて作成してみました。今回はTreasureDataの無料アカウントの作成と、importするサンプルソースについて書きたいと思います。
アカウントの作成
TreasureDataのページに行き、左の「製品」にフォーカスを当てると「今すぐ試す」というリンクが表示されます。この「今すぐ試す」リンクをまずはクリックします。
ページが遷移し、下のほうに赤字で「準備はよろしいですか?サインアップはこちらです。」のリンクがあるので、これをクリックします。すると以下のような画面が出るので、登録する情報を入力します。
全ての項目が入力必須のようですが、注意点は電話番号を国際電話番号にする必要があるらしいことです。「03~」で始まる電話番号を入力した所、エラーとなったので、日本を示す「+81」を先頭につけて登録したところ上手く行きました。(尚、国際電話番号にする場合は03 → +813のように、+81の後ろの0を取り除いてください)
「Sign Up」のボタンを押すと、アカウント作成が完了します。
サンプルソース
では、サンプルソースについてです。今回はファイルの内容を一括で登録する「import」メソッドを使用しました。処理としては
- CSVファイルを読み込む
- ファイルの内容を元に、importするmsgpack.gz形式のファイルを作成する
- 作成したmsgpack.gzファイルをimportする
を行っています。
尚、事前にTreasureData上にデータベースとテーブルが作成済みであることが前提です。
1.Gemfile
今回の処理に必要なgemをGemfileに記述し、$ bundle install します。
gem 'td' gem 'td-client' gem 'msgpack'
2.キーの取得
import処理を行うためには、TreasureDataより発行されるキーが必要です。このキーは、TreasureDataのページより確認することができます。TreasureDataのページにサインインした状態で、右上のユーザー名のリンクより「My Profile」をクリックします。Profileページの右側に「API Keys」という項目が表示されます。ここにパスワードを入力し、「Show Keys」ボタンを押下するとキーが表示されます。
もしくはTreasure Data Toolbeltがインストールされているなら、以下のコマンドでもキーを取得できます。
$ td apikey:show
3.import
先にimportする部分について解説します。サンプルソースは以下のようになります。
require 'csv' require 'zlib' class Sample TD_API_KEY = 'your api key' (中略) def self.import msgpack = create_msgpack(File.join(Rails.root, 'KEN_ALL_KAI.csv')) cln = TreasureData::Client.new(TD_API_KEY) File::open(msgpack) {|file| cln.import('sample_db', 'prefectures', 'msgpack.gz', file, 100) } true end (中略) end
5行目の「TD_API_KEY」には上記で確認したキーを記述します。11行目でTreasureData::Clientのインスタンスを作成しています。12行目でインポートするmsgpack.gzファイルを開き、13行目でimportしています。
import()メソッドの構文ですが、以下のようになります。
import(データベース名, テーブル名, インポートするファイルの形式, インポートするファイルのストリーム, ファイルサイズ)
注意すべきなのは
- インポートするファイルの形式はmsgpack.gzである
- インポートするファイルのパスではなく、ストリームを渡す必要がある
ことです。
4.msgpack.gzファイルの作成
最後にmsgpack.gzファイルの作成の作成についてです。上記の12行目で呼ばれていたcreate_msgpack()メソッドになります。
private def self.create_msgpack(file_path) outfile_path = "#{file_path}.msgpack.gz" CSV.open(file_path, 'rb') {|csv| header = csv.take(1)[0] File.open(outfile_path, "wb") {|mspack| gz = Zlib::GzipWriter.new(mspack) csv.each do |row| i = 0 data = Hash::new row.each do |item| data[header[i]] = item i = i + 1 end data['time'] = Time.now.to_i gz.write(data.to_msgpack) end gz.close } } outfile_path end
こちらについては、以下のサイトを参考にさせて頂きました。ありがとうございました。
CSVからMessagePack形式への変換スクリプト
処理としては
- CSVファイルをバイナリモードで開く
- CSVファイルを解析しつつ、20行目で「Time」項目を追加する
- msgpack.gzファイルに出力する
を行っています。「Time」項目を追加するのは、TreasureDataのテーブルにはデフォルトで「Time」カラムが存在するためです。
まとめ
以上でCSVファイルをTreasureDataにimportする処理を、Ruby on Railsにて実行することができました。私の環境で試したところ、13万件オーバーのCSVファイルが5秒以内に登録できました。尚、さらに件数が多い場合や、インポートするファイルサイズが大きい場合には「bulk_import」が適しているようです。これについても時間があれば書いてみようと思います。